package art.java.concurrency.chapter04;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author <a href="eric_zheng@lanzuo.com.cn">eric</a>
 * @version 1.0.0
 * Description:
 */
public class WaitNotify {

    private static boolean sign = true;
    private static Object lock = new Object();

    public static void main(String[] args) {
        Thread waitThread = new Thread(new Wait(), "waitThread");
        waitThread.start();

        Thread notifyThread = new Thread(new Notify(), "notifyThread");
        notifyThread.start();
    }

    static class Wait implements Runnable {

        @Override
        public void run() {
            // 加锁，拥有lock的Monitor，wait()之前，必须确保该线程获取了lock对象的锁
            synchronized (lock) {
                // 当接收到通知后 sign 为false
                while (sign) {
                    try {
                        System.out.println(Thread.currentThread() + " sign is true. waiting @ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                        lock.wait();
                    } catch (InterruptedException e) {

                    }
                }

                System.out.println(Thread.currentThread() + " sign is false. running @" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
            }
        }
    }

    static class Notify implements Runnable {

        @Override
        public void run() {
            synchronized (lock) {
                System.out.println(Thread.currentThread() + " hold the lock. notify @ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                lock.notifyAll();
                // 在通知之后修改状态
                sign = false;
                SleepUtils.second(5);
            }

            synchronized (lock) {
                System.out.println(Thread.currentThread() + " hold the lock again. notify @ " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                SleepUtils.second(5);
            }
        }


    }

    /**
     * Thread[waitThread,5,main] sign is true. waiting @ 15:08:04
     * Thread[notifyThread,5,main] hold the lock. notify @ 15:08:04
     * Thread[waitThread,5,main] sign is false. running @15:08:09
     * Thread[notifyThread,5,main] hold the lock again. notify @ 15:08:09
     */
}